/* @(#)DecKanGlGlyph.java 2010
 ** 
 ** Copyright (C) 2001-2011 by Steven D. Stamps
 **
 **             Trademarks & Copyrights
 ** Flywheel Management Science(TM) and FlywheelMS(TM) are exclusive
 ** trademarks of Steven D. Stamps and may only be used freely for
 ** the purpose of identifying the unforked version of this software.
 ** Subsequent forks (if any) may not use these trademarks.  All other
 ** rights are reserved.
 **
 ** DecKanGL (Decorated Kanban Glyph Language) and TribKn (Tribal Knowledge)
 ** are also exclusive trademarks of Steven D. Stamps.  These may be used
 ** freely within the unforked FlywheelMS application and documentation.
 ** All other rights are reserved.
 **
 ** Trademark information is available at
 ** <http://www.flywheelms.org/trademarks>
 **
 ** Flywheel Management Science(TM) is a copyrighted body of management
 ** metaphors, governance processes, and leadership techniques that is
 ** owned by Steven D. Stamps.  These copyrighted materials may be freely
 ** used, without alteration, by the community (users and developers)
 ** surrounding this GPL3-licensed software.  Additional copyright
 ** information is available at <http://www.flywheelms.org/copyrights>
 **
 **              GPL3 Software License
 ** This program is free software: you can use it, redistribute it and/or
 ** modify it under the terms of the GNU General Public License, version 3,
 ** as published by the Free Software Foundation. This program is distributed
 ** in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 ** even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 ** PURPOSE.  See the GNU General Public License for more details. You should
 ** have received a copy of the GNU General Public License, in a file named
 ** COPYING, along with this program.  If you cannot find your copy, see
 ** <http://www.gnu.org/licenses/gpl-3.0.html>.
 */
package com.fmscorp.deckangl.core;

import java.awt.AlphaComposite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import javax.swing.ImageIcon;

import com.fmscorp.deckangl.Decorator;
import com.fmscorp.deckangl.ImageManager;

/**
 * @author sstamps
 */
public class Glyph {

	private NounStatus nounStatus;
	private HashMap<DecoratorCanvasLocation, Decorator> decoratorMap;
	private Canvas canvas;
	private ImageIcon imageIcon;
	private ImageIcon imageIconZoom;
	private ImageIcon imageIconZoomAnnotated;
	private Date tribKnQualityTimeStamp;

	public Glyph(
			NounStatus aDecKanGlNounStatus,
			HashMap<DecoratorCanvasLocation, Decorator> decKanGlDecoratorMap,
			Canvas aDecKanGlCanvas) {
		this.nounStatus = aDecKanGlNounStatus;
		this.decoratorMap = decKanGlDecoratorMap;
		this.canvas = aDecKanGlCanvas;
		this.tribKnQualityTimeStamp = new Date();
	}
	
	public Date getTribKnQualityTimeStamp() {
		return this.tribKnQualityTimeStamp;
	}

	public NounStatus getNounStatus() {
		return this.nounStatus;
	}

	public ImageIcon getImageIconZoom() {
		if (this.imageIconZoom == null) {
			this.imageIconZoom = GlyphDictionary.buildDecKanGlImageIconZoom(this);
		}
		return imageIconZoom;
	}

	public ImageIcon getImageIconZoomAnnotated() {
		if (this.imageIconZoomAnnotated == null) {
			this.imageIconZoomAnnotated = GlyphDictionary.buildDecKanGlImageIconZoomAnnotated(this);
		}
		return imageIconZoomAnnotated;
	}

	public ImageIcon getImageIcon() {
		if (this.imageIcon == null) {
			BufferedImage theBufferedImageCanvas = new BufferedImage(
					getCanvas().getWidth(),
					getCanvas().getHeight(),
					BufferedImage.TYPE_INT_ARGB);
			Graphics theGraphicsContext = theBufferedImageCanvas.getGraphics();
			drawBackground(theBufferedImageCanvas, theGraphicsContext);			
			theGraphicsContext.setColor(getCanvas().getNounBackgroundColor());
			theGraphicsContext.fillRect(
					getCanvas().getNounStatusImageCanvasPositionX() - 2, 
					getCanvas().getNounStatusImageCanvasPositionY() - 2,
					getNounStatus().getImageIcon().getImage().getWidth(null) + 4,
					getNounStatus().getImageIcon().getImage().getHeight(null) + 4 );
			Graphics2D theGraphics2dCanvas = theBufferedImageCanvas.createGraphics();
			theGraphics2dCanvas.setComposite(AlphaComposite.SrcOver);
			theGraphics2dCanvas.drawImage(
					getNounStatus().getImageIcon().getImage(),
					getCanvas().getNounStatusImageCanvasPositionX(),
					getCanvas().getNounStatusImageCanvasPositionY(),
					null);  // nobody needs to be notified while we are drawing
			for (Decorator theDecKanGlDecorator : getDecoratorMap().values()) {
				if (!theDecKanGlDecorator.getImageIconPath().equals(ImageManager.icon_path_DECORATOR_TRANSPARENT) &&
						theDecKanGlDecorator.isEnabled() ) {
					drawDecorator(
							theDecKanGlDecorator.getImageIcon(),
							theGraphics2dCanvas,
							theDecKanGlDecorator.getTribKn().getLogicalCanvasLocation().getCanvasPositionX(this),
							theDecKanGlDecorator.getTribKn().getLogicalCanvasLocation().getCanvasPositionY(this) );
				}
			}
			this.imageIcon = new ImageIcon(theBufferedImageCanvas);
		}
		return this.imageIcon;
	}

	// TODO Needs more work to smooth corners.
	// 		Could be an algorithm instead of these constants.
	private void drawBackground(
			BufferedImage theBufferedImageCanvas,
			Graphics theGraphicsContext ) {
		theGraphicsContext.setColor(getCanvas().getDecoratorBackgroundColor());
		theGraphicsContext.fillRect(5, 0, theBufferedImageCanvas.getWidth() - 10, 1);
		theGraphicsContext.fillRect(3, 1, theBufferedImageCanvas.getWidth() - 6, 1);
		theGraphicsContext.fillRect(2, 2, theBufferedImageCanvas.getWidth() - 4, 1);
		theGraphicsContext.fillRect(1, 3, theBufferedImageCanvas.getWidth() - 2, 2);
		theGraphicsContext.fillRect(0, 5,
				theBufferedImageCanvas.getWidth(),
				theBufferedImageCanvas.getHeight() - 10 );
		theGraphicsContext.fillRect(
				1,
				theBufferedImageCanvas.getHeight() - 5,
				theBufferedImageCanvas.getWidth() - 2,
				2);
		theGraphicsContext.fillRect(
				2,
				theBufferedImageCanvas.getHeight() - 3,
				theBufferedImageCanvas.getWidth() - 4,
				1);
		theGraphicsContext.fillRect(
				3,
				theBufferedImageCanvas.getHeight() - 2,
				theBufferedImageCanvas.getWidth() - 6,
				1);
		theGraphicsContext.fillRect(
				5,
				theBufferedImageCanvas.getHeight() - 1,
				theBufferedImageCanvas.getWidth() - 10,
				1);
		// top corners
		theGraphicsContext.setColor(getCanvas().getDecoratorBackgroundColorMediumAlpha());
		theGraphicsContext.fillRect(4, 0, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 5, 0, 1, 1);
		theGraphicsContext.fillRect(2, 1, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 3, 1, 1, 1);
		theGraphicsContext.fillRect(1, 2, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 2, 2, 1, 1);
		theGraphicsContext.fillRect(0, 4, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 1, 4, 1, 1);
		theGraphicsContext.setColor(getCanvas().getDecoratorBackgroundColorLightAlpha());
		theGraphicsContext.fillRect(3, 0, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 4, 0, 1, 1);
		theGraphicsContext.fillRect(0, 3, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 1, 3, 1, 1);
		// bottom corners
		theGraphicsContext.setColor(getCanvas().getDecoratorBackgroundColorMediumAlpha());
		theGraphicsContext.fillRect(0, theBufferedImageCanvas.getHeight() - 5, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 1, theBufferedImageCanvas.getHeight() - 5, 1, 1);
		theGraphicsContext.fillRect(4, theBufferedImageCanvas.getHeight() - 1, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 5, theBufferedImageCanvas.getHeight() - 1, 1, 1);
		theGraphicsContext.fillRect(1, theBufferedImageCanvas.getHeight() - 3, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 2, theBufferedImageCanvas.getHeight() - 3, 1, 1);
		theGraphicsContext.fillRect(2, theBufferedImageCanvas.getHeight() - 2, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 3, theBufferedImageCanvas.getHeight() - 2, 1, 1);
		theGraphicsContext.setColor(getCanvas().getDecoratorBackgroundColorLightAlpha());
		theGraphicsContext.fillRect(0, theBufferedImageCanvas.getHeight() - 4, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 1, theBufferedImageCanvas.getHeight() - 4, 1, 1);
		theGraphicsContext.fillRect(3, theBufferedImageCanvas.getHeight() - 1, 1, 1);
		theGraphicsContext.fillRect(theBufferedImageCanvas.getWidth() - 4, theBufferedImageCanvas.getHeight() - 1, 1, 1);
	}

	private static void drawDecorator(
			ImageIcon anImageIcon,
			Graphics2D aGraphics2D,
			int aPositionX,
			int aPositionY) {
		if (anImageIcon != null) {
			aGraphics2D.drawImage(
					anImageIcon.getImage(),
					aPositionX,
					aPositionY,
					null);  // nobody needs to be notified while we are drawing
		}
	}

	public HashMap<DecoratorCanvasLocation, Decorator> getDecoratorMap() {
		return decoratorMap;
	}

	public Decorator getDecorator(String aDecoratorName) {
		return (Decorator) this.decoratorMap.get(aDecoratorName);
	}

	public Noun getNoun() {
		return getNounStatus().getNoun();
	}

	public Canvas getCanvas() {
		return this.canvas;
	}
	
	public ArrayList<String> getLeftAnnotations() {
		ArrayList<String> theArrayList = new ArrayList<String>();
		if (GlyphDictionary.decoratorsUseZone(
				this.decoratorMap, CanvasZone.TOP_ZONE)) {
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.top_zone_LEFT)));
		}
		if (	GlyphDictionary.decoratorsUseZone(
					this.decoratorMap, CanvasZone.LEFT_ZONE) || 
				GlyphDictionary.decoratorsUseZone(
					this.decoratorMap, CanvasZone.RIGHT_ZONE) ) {
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.left_zone_TOP)));
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.left_zone_MIDDLE)));
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.left_zone_BOTTOM)));
		}
		if (GlyphDictionary.decoratorsUseZone(
				this.decoratorMap, CanvasZone.BOTTOM_ZONE)) {
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.bottom_zone_LEFT)));
		}
		return theArrayList;
	}
	
	public ArrayList<String> getRightAnnotations() {
		ArrayList<String> theArrayList = new ArrayList<String>();
		if (GlyphDictionary.decoratorsUseZone(
				this.decoratorMap, CanvasZone.TOP_ZONE)) {
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.top_zone_RIGHT)));
		}
		if (	GlyphDictionary.decoratorsUseZone(
					this.decoratorMap, CanvasZone.LEFT_ZONE) || 
				GlyphDictionary.decoratorsUseZone(
					this.decoratorMap, CanvasZone.RIGHT_ZONE) ) {
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.right_zone_TOP)));
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.right_zone_MIDDLE)));
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.right_zone_BOTTOM)));
		}
		if (GlyphDictionary.decoratorsUseZone(
				this.decoratorMap, CanvasZone.BOTTOM_ZONE)) {
			theArrayList.add(getAnnotation(getDecoratorForLocation(DecoratorCanvasLocation.bottom_zone_RIGHT)));
		}
		return theArrayList;
	}

	private String getAnnotation(Decorator aDecorator) {
		if (aDecorator == null) {
			return "";
		}
		return aDecorator.getName();
	}

	private Decorator getDecoratorForLocation(
			DecoratorCanvasLocation aCanvasLocation) {
		for (Decorator theDecKanGlDecorator : this.decoratorMap.values()) {
			if (theDecKanGlDecorator.getTribKn().getLogicalCanvasLocation() == aCanvasLocation) {
				return theDecKanGlDecorator;
			}
		}
		return null;
	}

}